/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Drawing.Drawing2D;

namespace MyPhotoIndex.Utilities
{
    public static class ImageAlgo
    {
        public static Size GetImageProportionalSize(SizeF imageSize, SizeF requestedSize)
        {
            float realPicWidth = requestedSize.Width;
            float realpicHeight = requestedSize.Height;

            if (IsPortraitImage(imageSize) ||
                imageSize.Width == imageSize.Height)
            {
                float factor = (float)imageSize.Height / (float)requestedSize.Height;
                realPicWidth = imageSize.Width / factor;
            }
            else
            if (IsLandscapeImage(imageSize))
            {
                float factor = (float)imageSize.Width / (float)requestedSize.Width;
                realpicHeight = imageSize.Height / factor;
                if (realpicHeight > requestedSize.Height)
                {
                    float heightFactor = (float)realpicHeight / (float)requestedSize.Height;
                    realPicWidth = realPicWidth / heightFactor;
                    realpicHeight = requestedSize.Height;
                }
            }

            return new Size((int)Math.Ceiling(realPicWidth), (int)Math.Ceiling(realpicHeight));
        }

        public static SizeF GetImageProportionalSizeF(SizeF imageSize, SizeF requestedSize)
        {
            float realPicWidth = requestedSize.Width;
            float realpicHeight = requestedSize.Height;

            if (IsPortraitImage(imageSize) || 
                imageSize.Width == imageSize.Height)
            {
                float factor = imageSize.Height / requestedSize.Height;
                realPicWidth = imageSize.Width / factor;
            }
            else
                if (IsLandscapeImage(imageSize))
                {
                    float factor = imageSize.Width / requestedSize.Width;
                    realpicHeight = imageSize.Height / factor;
                    if (realpicHeight > requestedSize.Height)
                    {
                        float heightFactor = realpicHeight / requestedSize.Height;
                        realPicWidth = realPicWidth / heightFactor;
                        realpicHeight = requestedSize.Height;
                    }
                }

            return new SizeF(realPicWidth, realpicHeight);
        }

        public static bool IsLandscapeImage(Size imageSize)
        {
            return (imageSize.Width > imageSize.Height);
        }

        public static bool IsPortraitImage(Size imageSize)
        {
            return (imageSize.Width < imageSize.Height);
        }

        public static bool IsLandscapeImage(SizeF imageSize)
        {
            return (imageSize.Width > imageSize.Height);
        }

        public static bool IsPortraitImage(SizeF imageSize)
        {
            return (imageSize.Width < imageSize.Height);
        }

        public static void RotateImageAnimation(Graphics graphics1, Image image, Rectangle drawingRect, Rectangle maxRect, int fromAngle, int toAngle, Color backgroundColor)
        {
            Rectangle clipRect = new Rectangle(maxRect.X + 2, maxRect.Y, maxRect.Width - 2, maxRect.Height);
            graphics1.Clip = new Region(clipRect);
            
            Size destSize;

            using (Bitmap canvas = new Bitmap(clipRect.Width, clipRect.Height, graphics1))
            {
                using (Graphics graphics = Graphics.FromImage(canvas))
                {
                    destSize = ImageAlgo.GetImageProportionalSize(new Size(image.Height, image.Width), maxRect.Size);

                    float scaleMax = (float)destSize.Width / ((float)drawingRect.Width);
                    float scaleMaxY = (float)destSize.Height / ((float)drawingRect.Height);
                    scaleMax = 1.0f - (scaleMax + scaleMaxY) / 2;

                    float scaleStep = scaleMax / (((toAngle > fromAngle) ? (toAngle - fromAngle) : (fromAngle - toAngle)) / 5f);
                    float scaleX = 1.0f;

                    float x = drawingRect.X;
                    float y = drawingRect.Y;

                    int width = drawingRect.Width;
                    int height = drawingRect.Height;

                    int i = fromAngle;

                    Image imageToDraw = image;//new Bitmap(image, (int)(drawingRect.Width * scaleX), (int)(drawingRect.Height * scaleX));
                    int itr = 0;
                    while (true)
                    {
                        graphics.Clear(backgroundColor);
                        Matrix X = new Matrix();

                        X.RotateAt(i, new PointF((clipRect.Width / 2), (clipRect.Height / 2)));

                        graphics.Transform = X;
                        // Draw image

                        x = ((clipRect.Width - (width * scaleX)) / 2);
                        y =  ((clipRect.Height - (height * scaleX)) / 2);

                        graphics.DrawImage(imageToDraw, x, y, (int)(drawingRect.Width * scaleX), (int)(drawingRect.Height * scaleX));
                        graphics1.DrawImage(canvas, clipRect);
                        Thread.Sleep(10);

                        scaleX -= scaleStep;
                        // scaleX = scaleMax;
                        itr++;
                        if (i == toAngle)
                        {
                            break;
                        }

                        if (fromAngle < toAngle)
                        {
                            i += Math.Min(5, toAngle - i);
                        }
                        else
                        {
                            i -= Math.Min(5, i - toAngle);
                        }
                    }
                }
            }
        }
    }
}
